package com.cmy.webCore.handler;

import cn.hutool.core.convert.Convert;
import com.cmy.webCore.enums.ResultCode;
import com.cmy.common.exception.CommonException;
import com.cmy.common.utils.ThrowableUtil;
import com.cmy.webCore.exception.EntityExistException;
import com.cmy.webCore.exception.EntityNotFoundException;
import com.cmy.webCore.utils.MessageUtil;
import com.cmy.webCore.vo.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;


/**
 * @Author:Cmy
 * @Date:2022/11/22-14:53
 * @Description:全局异常捕获处理
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理所有不可知的异常
     */
    @ExceptionHandler(Throwable.class)
    public R handleException(Throwable e){
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        String message = e.getMessage();
        if (e instanceof NullPointerException){
            message = "NPE_ERROR";
        }
        String finalMessage = MessageUtil.message(message);
        return R.fail(ResultCode.ERROR,finalMessage);
    }

    /**
     * 空指针异常
     * @param e
     * @return
     */
    @ExceptionHandler(NullPointerException.class)
    public R handlerNullPointException(NullPointerException e){
        log.error(ThrowableUtil.getStackTrace(e));
        String message = "NPE_ERROR";
        String npeMessage = MessageUtil.message(message);
        return R.fail(ResultCode.ERROR,npeMessage);
    }

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(value = CommonException.class)
    public R handlerCommonException(CommonException e) {
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        String message = MessageUtil.message(e.getMessage());
        return R.fail(ResultCode.ERROR,message);
    }

    /**
     * 处理 EntityExist 实体类已存在
     */
    @ExceptionHandler(value = EntityExistException.class)
    public R entityExistException(EntityExistException e) {
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        return R.fail(ResultCode.BAD_REQUEST.getCode(),e.getMessage());
    }

    /**
     * 处理 EntityNotFound 实体类不存在
     */
    @ExceptionHandler(value = EntityNotFoundException.class)
    public R entityNotFoundException(EntityNotFoundException e) {
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        return R.fail(ResultCode.BAD_REQUEST.getCode(),e.getMessage());
    }



    /**
     * Json请求体校验异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        String message = objectError.getDefaultMessage();
        String filed = null;
        if (objectError instanceof FieldError) {
             filed = ((FieldError) objectError).getField();
        }
        if (StringUtils.isNotBlank(filed)){
            message = MessageUtil.message(message,filed);
        }else {
            message = MessageUtil.message(message);
        }
        return R.fail(ResultCode.BAD_REQUEST.getCode(),message);
    }

    /**
     * 违反验证规则
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public R handlerConstraintViolationException(ConstraintViolationException e){
        log.error(ThrowableUtil.getStackTrace(e));
        ConstraintViolation<?> constraintViolation =(ConstraintViolation<?>)e.getConstraintViolations().toArray()[0];
        String message = constraintViolation.getMessage();
        String propertyPath = Convert.toStr(constraintViolation.getPropertyPath());
        String[] propertyAndPath = propertyPath.split("\\.");
        String theMessage = MessageUtil.message(message, propertyAndPath[1]);
        return R.fail(ResultCode.BAD_REQUEST.getCode(),theMessage);
    }

    /**
     * 参数丢失
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public R handlerMissingServletRequestParameterException(MissingServletRequestParameterException e){
        log.error(ThrowableUtil.getStackTrace(e));
        String parameterName = e.getParameterName();
        String message = MessageUtil.message("FILED_IS_NOT_PRESENT", parameterName);
        return R.fail(ResultCode.BAD_REQUEST.getCode(),message);
    }

    /**
     * 类型不匹配
     * @return
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public R handlerMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e){
        log.error(ThrowableUtil.getStackTrace(e));
        String filed = e.getName();
        String theMessage = MessageUtil.message("FILED_TYPE_IS_WRONG", filed);
        return R.fail(ResultCode.BAD_REQUEST.getCode(),theMessage);
    }

    @ExceptionHandler(BindException.class)
    public R handlerBindException(BindException e){
        log.info(ThrowableUtil.getStackTrace(e));
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        String message = objectError.getDefaultMessage();
        String filed = null;
        if (objectError instanceof FieldError) {
            filed = ((FieldError) objectError).getField();
        }
        if (StringUtils.isNotBlank(filed)){
            message = MessageUtil.message(message,filed);
        }else {
            message = MessageUtil.message(message);
        }
        return R.fail(ResultCode.BAD_REQUEST.getCode(),message);
    }



}

    